package com.fy.opengltest.renderPicture;

import android.opengl.GLES20;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import static com.fy.opengltest.ShaderUtils.checkGlError;

/**
 * Created by android on 10/8/17.
 */

public class Circle2rectangle {


    private static final int sPositionDataSize = 3;
    private static final int sTextureCoordinateDataSize = 2;

    private FloatBuffer mVerticesBuffer;
    private FloatBuffer mTexCoordinateBuffer;
    private ShortBuffer indexBuffer;
    private int mNumIndices;


    public Circle2rectangle() {
        initVertexData(0.5f, 200, 200);
    }

    /*
    * @param radius in range (0, 0.5)
    * @param sectors  in range [2, 360)
    * @param rings  in range (1, +oo)
    * */
    private void initVertexData(float radius, int sectors, int rings) {

        int nodeCount = (sectors + 1) * (rings + 1);
        float vertexs[] = new float[nodeCount * 3];
        float texcoords[] = new float[nodeCount * 2];
        short indices[] = new short[nodeCount * 6];

        int offset_texcoord = 0;
        int offset_vertex = 0;

        float angle;
        float radiusInRings;

        float sec_x;
        float sec_y;

        //for circle point
        for (int i = 0; i <= sectors; i++) {
            angle = 360f / (float) sectors * (float) i - 90f;
            sec_x = 1f - 2f / (float) sectors * (float) i;

            float cos_angle = (float) Math.cos(Math.toRadians(angle));
            float sin_angle = (float) Math.sin(Math.toRadians(angle));

            for (int j = 0; j <= rings; j++) {
                radiusInRings = (radius / (float) rings) * (float) j;
                texcoords[offset_texcoord++] = 0.5f + radiusInRings * cos_angle;
                texcoords[offset_texcoord++] = 0.5f + radiusInRings * sin_angle;

//                sec_y = 0.25f - 0.5f / (float) rings * (float) j;
                sec_y = 0.5f - 1f / (float) rings * (float) j;
                vertexs[offset_vertex++] = sec_x;
                vertexs[offset_vertex++] = sec_y;
                vertexs[offset_vertex++] = 0;
            }
        }

        int counter = 0;
        for (int x = 0; x < sectors; x++) {
            for (int y = 0; y < rings; y++) {
                indices[counter++] = (short) (x * (rings + 1) + y);
                indices[counter++] = (short) (x * (rings + 1) + y + 1);
                indices[counter++] = (short) ((x + 1) * (rings + 1) + y);
                indices[counter++] = (short) (x * (rings + 1) + y + 1);
                indices[counter++] = (short) ((x + 1) * (rings + 1) + y + 1);
                indices[counter++] = (short) ((x + 1) * (rings + 1) + y);
            }
        }

        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (# of coordinate values * 4 bytes per float)
                vertexs.length * 4);
        bb.order(ByteOrder.nativeOrder());
        FloatBuffer vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(vertexs);
        vertexBuffer.position(0);

        // initialize vertex byte buffer for shape coordinates
        ByteBuffer cc = ByteBuffer.allocateDirect(
                texcoords.length * 4);
        cc.order(ByteOrder.nativeOrder());
        FloatBuffer texBuffer = cc.asFloatBuffer();
        texBuffer.put(texcoords);
        texBuffer.position(0);

        // initialize byte buffer for the draw list
        ByteBuffer dlb = ByteBuffer.allocateDirect(
                // (# of coordinate values * 2 bytes per short)
                indices.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        indexBuffer = dlb.asShortBuffer();
        indexBuffer.put(indices);
        indexBuffer.position(0);

        mTexCoordinateBuffer = texBuffer;
        mVerticesBuffer = vertexBuffer;
        mNumIndices = indices.length;
    }

    public void uploadVerticesBuffer(int positionHandle) {
        FloatBuffer vertexBuffer = getVerticesBuffer();
        if (vertexBuffer == null) return;
        vertexBuffer.position(0);

        GLES20.glVertexAttribPointer(positionHandle, sPositionDataSize, GLES20.GL_FLOAT, false, 0, vertexBuffer);
        checkGlError("glVertexAttribPointer maPosition");
        GLES20.glEnableVertexAttribArray(positionHandle);
        checkGlError("glEnableVertexAttribArray maPositionHandle");
    }

    public void uploadTexCoordinateBuffer(int textureCoordinateHandle) {
        FloatBuffer textureBuffer = getTexCoordinateBuffer();
        if (textureBuffer == null) return;
        textureBuffer.position(0);

        GLES20.glVertexAttribPointer(textureCoordinateHandle, sTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, textureBuffer);
        checkGlError("glVertexAttribPointer maTextureHandle");
        GLES20.glEnableVertexAttribArray(textureCoordinateHandle);
        checkGlError("glEnableVertexAttribArray maTextureHandle");
    }

    public FloatBuffer getVerticesBuffer() {
        return mVerticesBuffer;
    }

    public FloatBuffer getTexCoordinateBuffer() {
        return mTexCoordinateBuffer;
    }

    public void draw() {
        indexBuffer.position(0);
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
//        GLES20.glDrawElements(GLES20.GL_LINES, mNumIndices, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
    }

}
